#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import re
import weakref
from datetime import datetime
from typing import Dict, List, Set, Optional, Tuple
from enum import Enum
import logging
from tree_sitter import Tree, Node
# 导入数据结构
from parser.refactor.data_structures import (
    ClassInfo, ParserContext, DependencyContext, DependencyType,
    MethodInfo, FieldInfo, AnnotationInfo, GraphNodeInfo, GraphEdgeInfo,
    MetadataInfo, RelationshipInfo, RelationshipCollection,
    ClassType, Visibility, FileInfo, ParameterInfo, CommentInfo
)
from parser.refactor.java_metadata_extractor.java_metadata_extractor import JavaMetadataExtractor
from parser.refactor.java_metadata_extractor.java_method_extractor import JavaMethodExtractor
from parser.refactor.java_node_type import (JavaNodeType)

logger = logging.getLogger(__name__)


class JavaClassExtractor(JavaMetadataExtractor):
    """Java类元数据提取器"""

    def __init__(self, class_name_map: Dict[str, ClassInfo]):
        """
        初始化Java解析器

        Args:
            class_name_map: 类名到类信息的映射
        """
        super().__init__()
        self.class_name_map = class_name_map

    def extract_class_info(self, file_path: str, node: Node, code_bytes: bytes,
                           package_name: str, import_list: List[str]) -> ClassInfo:
        """
        从类声明节点提取类信息

        Args:
            file_path: 文件路径
            node: 类声明节点
            code_bytes: 源代码字节
            package_name: 包名
            import_list: 当前import列表(已去除import、static、;)

        Returns:
            ClassInfo对象

        Raises:
            ValueError: 无法获取必要的类信息时
        """
        try:
            # 1. 提取类名
            class_name = None
            for child in node.children:
                if child.type == JavaNodeType.IDENTIFIER:
                    class_name = self.get_node_text(child, code_bytes)
                    break

            if not class_name:
                raise ValueError("无法获取类名")

            # 2. 提取修饰符
            modifiers = set()
            visibility = Visibility.PACKAGE  # 默认包可见性

            modifier_node = None
            for child in node.children:
                if child.type == JavaNodeType.MODIFIERS:
                    modifier_node = child
                    break

            if modifier_node:
                modifier_text = self.get_node_text(modifier_node, code_bytes)
                modifiers = set(modifier_text.split())

                # 设置可见性
                if 'public' in modifiers:
                    visibility = Visibility.PUBLIC.value
                elif 'protected' in modifiers:
                    visibility = Visibility.PROTECTED.value
                elif 'private' in modifiers:
                    visibility = Visibility.PRIVATE.value

            # 3. 确定类型
            class_type = ClassType.CLASS.value  # 默认为普通类
            if node.type == JavaNodeType.INTERFACE_DECLARATION:
                class_type = ClassType.INTERFACE.value
            elif node.type == JavaNodeType.ENUM_DECLARATION:
                class_type = ClassType.ENUM.value
            elif node.type == JavaNodeType.ANNOTATION_DECLARATION:
                class_type = ClassType.ANNOTATION.value

            # 4. 构建完整类名
            full_name = class_name
            if package_name:
                full_name = f"{package_name}.{class_name}"

            # 5. 获取类源代码
            source_code = self.get_node_text(node, code_bytes)

            """
            获取当前类对其他实体的关联, 并将其full_name组成的List置入对应字段
            以下步骤:
            6. 提取实现的方法 -> methods
            7. 提取父类的信息 -> super_classes
            8. 提取实现的接口 -> implemented_interfaces
            9. 提取内部类信息 -> inner_classes
            10. 提取注解信息 -> annotations
            """

            # 6. 提取实现的方法
            methods = []
            for class_body_node in node.children:
                if class_body_node.type in [JavaNodeType.CLASS_BODY, JavaNodeType.INTERFACE_BODY]:
                    for child in class_body_node.children:
                        if child.type == JavaNodeType.METHOD_DECLARATION:
                            java_method_extractor = JavaMethodExtractor(self.class_name_map)
                            method_info = java_method_extractor.extract_method_info(file_path, child, code_bytes, package_name, import_list)
                            if method_info:
                                methods.append(method_info.full_name)

            # 7. 提取父类的信息
            super_classes = []
            for child in node.children:
                if child.type == JavaNodeType.SUPERCLASS:
                    for superclass_node in child.children:
                        if superclass_node.type == JavaNodeType.TYPE_IDENTIFIER:
                            super_class = self.get_node_text(superclass_node, code_bytes)
                            # 解析继承父类的全限定名
                            super_class_full_name = self.extract_full_name_by_imports(
                                super_class,
                                package_name,
                                import_list,
                                self.class_name_map
                            )
                            super_classes.append(super_class_full_name)

            # 8. 提取实现的接口
            implemented_interfaces = []
            for child in node.children:
                if child.type == JavaNodeType.SUPER_INTERFACES:
                    for interface_node in child.children:
                        if interface_node.type == JavaNodeType.TYPE_LIST:
                            for type_node in interface_node.children:
                                interface_name = self.get_node_text(type_node, code_bytes)
                                # 解析实现接口的全限定名
                                interface_full_name = self.extract_full_name_by_imports(
                                    interface_name,
                                    package_name,
                                    import_list,
                                    self.class_name_map
                                )
                                implemented_interfaces.append(interface_full_name)

            # 9. 提取内部类信息
            inner_classes = []
            for class_body_node in node.children:
                if class_body_node.type == JavaNodeType.CLASS_BODY:
                    for child in class_body_node.children:
                        if child.type in [JavaNodeType.CLASS_DECLARATION,
                                               JavaNodeType.INTERFACE_DECLARATION,
                                               JavaNodeType.ENUM_DECLARATION]:
                            inner_class = self.extract_class_info(
                            file_path,
                            child,
                            code_bytes,
                            package_name,
                            import_list
                            )
                            if inner_class:
                                inner_classes.append(inner_class.full_name)


            # 10. 提取类的注解
            annotations = self._extract_annotations_full_name(node, code_bytes, package_name, import_list)

            # 11. 创建并返回ClassInfo对象
            return ClassInfo(
                name=class_name,
                full_name=full_name,
                package=package_name or "",
                file_path=file_path,
                type=class_type,
                visibility=visibility,
                is_abstract='abstract' in modifiers,
                is_static='static' in modifiers,
                is_final='final' in modifiers,
                source_code = source_code,
                methods = methods,
                imports = import_list,
                super_classes=super_classes,
                implemented_interfaces=implemented_interfaces,
                inner_classes=inner_classes,
                annotations=annotations
            )

        except Exception as e:
            logger.error(f"提取类信息时出错: {str(e)}")
            raise


    def _extract_annotations_full_name(self, node: Node, code_bytes: bytes,
                                      package_name: str, import_list: List[str]) -> List[str]:
        """
        提取类的注解全限定名列表

        Args:
            node: 类声明节点
            code_bytes: 源代码字节
            package_name: 当前包名
            import_list: import语句列表

        Returns:
            List[str]: 注解全限定名列表
        """
        annotations = []

        try:
            # 查找修饰符节点（包含注解）
            modifier_node = None
            for child in node.children:
                if child.type == JavaNodeType.MODIFIERS:
                    modifier_node = child
                    break

            if not modifier_node:
                return annotations

            # 遍历所有注解节点
            for child in modifier_node.children:
                if child.type in [JavaNodeType.ANNOTATION, JavaNodeType.MARKER_ANNOTATION]:
                    # 提取注解名称
                    annotation_name = None
                    for anno_child in child.children:
                        if anno_child.type == JavaNodeType.IDENTIFIER:
                            annotation_name = self.get_node_text(anno_child, code_bytes)
                            break

                    if not annotation_name:
                        continue

                    # 解析注解的全限定名
                    annotation_full_name = self.extract_full_name_by_imports(
                        annotation_name,
                        package_name,
                        import_list,
                        self.class_name_map
                    )

                    annotations.append(annotation_full_name)

            return annotations

        except Exception as e:
            logger.error(f"提取注解信息时出错: {str(e)}")
            return []

